const express = require('express');
const cron = require('node-cron');
const router = express.Router();
const { authenticateToken } = require('./auth');
const db = require('../database/connection');

// Get system settings
async function getSystemSetting(key) {
  const setting = await db.query(
    'SELECT setting_value FROM system_settings WHERE setting_key = ?',
    [key]
  );
  return setting.length > 0 ? setting[0].setting_value : null;
}

// Stake tokens
router.post('/stake', authenticateToken, async (req, res) => {
  try {
    const { amount } = req.body;
    const userId = req.user.userId;

    if (!amount || amount <= 0) {
      return res.status(400).json({ error: 'Amount must be greater than 0' });
    }

    // Check user balance
    const balance = await db.query(
      'SELECT available_balance FROM user_balances WHERE user_id = ?',
      [userId]
    );

    if (balance.length === 0) {
      return res.status(404).json({ error: 'User balance not found' });
    }

    if (parseFloat(balance[0].available_balance) < parseFloat(amount)) {
      return res.status(400).json({ error: 'Insufficient available balance' });
    }

    // Get interest rate
    const interestRate = parseFloat(await getSystemSetting('daily_interest_rate')) || 0.01;

    // Create staking record
    const result = await db.transaction(async (connection) => {
      // Update user balances
      await connection.execute(
        `UPDATE user_balances
         SET available_balance = available_balance - ?,
             staked_balance = staked_balance + ?,
             updated_at = CURRENT_TIMESTAMP
         WHERE user_id = ?`,
        [amount, amount, userId]
      );

      // Create staking record
      const [stakingResult] = await connection.execute(
        `INSERT INTO staking_records (user_id, amount, staking_date, interest_rate, status)
         VALUES (?, ?, CURDATE(), ?, 'active')`,
        [userId, amount, interestRate]
      );

      return {
        stakingId: stakingResult.insertId,
        stakingDate: new Date().toISOString().split('T')[0],
        interestRate
      };
    });

    res.json({
      message: 'Tokens staked successfully',
      stakingId: result.stakingId,
      amount,
      stakingDate: result.stakingDate,
      interestRate: result.interestRate
    });

  } catch (error) {
    console.error('Staking error:', error);
    res.status(500).json({ error: 'Failed to stake tokens' });
  }
});

// Unstake tokens
router.post('/unstake', authenticateToken, async (req, res) => {
  try {
    const { stakingId, amount } = req.body;
    const userId = req.user.userId;

    if (!stakingId || !amount || amount <= 0) {
      return res.status(400).json({ error: 'Staking ID and amount are required' });
    }

    // Get staking record
    const stakingRecord = await db.query(
      'SELECT amount, status FROM staking_records WHERE id = ? AND user_id = ?',
      [stakingId, userId]
    );

    if (stakingRecord.length === 0) {
      return res.status(404).json({ error: 'Staking record not found' });
    }

    if (stakingRecord[0].status !== 'active') {
      return res.status(400).json({ error: 'Staking record is not active' });
    }

    if (parseFloat(stakingRecord[0].amount) < parseFloat(amount)) {
      return res.status(400).json({ error: 'Amount exceeds staked amount' });
    }

    await db.transaction(async (connection) => {
      // Update user balances
      await connection.execute(
        `UPDATE user_balances
         SET available_balance = available_balance + ?,
             staked_balance = staked_balance - ?,
             updated_at = CURRENT_TIMESTAMP
         WHERE user_id = ?`,
        [amount, amount, userId]
      );

      // Update staking record
      if (parseFloat(stakingRecord[0].amount) === parseFloat(amount)) {
        // Complete staking record if full amount is unstaked
        await connection.execute(
          'UPDATE staking_records SET status = "completed" WHERE id = ?',
          [stakingId]
        );
      } else {
        // Reduce staked amount if partial unstake
        await connection.execute(
          'UPDATE staking_records SET amount = amount - ? WHERE id = ?',
          [amount, stakingId]
        );
      }
    });

    res.json({
      message: 'Tokens unstaked successfully',
      amount,
      stakingId
    });

  } catch (error) {
    console.error('Unstaking error:', error);
    res.status(500).json({ error: 'Failed to unstake tokens' });
  }
});

// Get staking records
router.get('/records', authenticateToken, async (req, res) => {
  try {
    const userId = req.user.userId;
    const { page = 1, limit = 20, status } = req.query;
    const offset = (page - 1) * limit;

    let whereClause = 'WHERE user_id = ?';
    const params = [userId];

    if (status) {
      whereClause += ' AND status = ?';
      params.push(status);
    }

    const records = await db.query(
      `SELECT id, amount, staking_date, interest_rate, status, created_at, updated_at
       FROM staking_records
       ${whereClause}
       ORDER BY created_at DESC
       LIMIT ? OFFSET ?`,
      [...params, parseInt(limit), offset]
    );

    const totalResult = await db.query(
      `SELECT COUNT(*) as total FROM staking_records ${whereClause}`,
      params
    );

    res.json({
      records,
      pagination: {
        page: parseInt(page),
        limit: parseInt(limit),
        total: totalResult[0].total,
        totalPages: Math.ceil(totalResult[0].total / limit)
      }
    });

  } catch (error) {
    console.error('Staking records error:', error);
    res.status(500).json({ error: 'Failed to fetch staking records' });
  }
});

// Get available interest to claim
router.get('/interest', authenticateToken, async (req, res) => {
  try {
    const userId = req.user.userId;

    const interest = await db.query(
      `SELECT id, interest_amount, distribution_date, claim_deadline, is_claimed
       FROM interest_distributions
       WHERE user_id = ? AND is_claimed = FALSE AND claim_deadline > NOW()
       ORDER BY distribution_date DESC`,
      [userId]
    );

    const totalAvailable = interest.reduce((sum, item) => sum + parseFloat(item.interest_amount), 0);

    res.json({
      interest,
      totalAvailable,
      count: interest.length
    });

  } catch (error) {
    console.error('Interest fetch error:', error);
    res.status(500).json({ error: 'Failed to fetch available interest' });
  }
});

// Claim interest
router.post('/claim-interest', authenticateToken, async (req, res) => {
  try {
    const { interestIds } = req.body;
    const userId = req.user.userId;

    if (!interestIds || !Array.isArray(interestIds) || interestIds.length === 0) {
      return res.status(400).json({ error: 'Interest IDs are required' });
    }

    // Verify interest records
    const interestRecords = await db.query(
      `SELECT id, interest_amount, claim_deadline, is_claimed
       FROM interest_distributions
       WHERE id IN (?) AND user_id = ? AND is_claimed = FALSE AND claim_deadline > NOW()`,
      [interestIds, userId]
    );

    if (interestRecords.length === 0) {
      return res.status(404).json({ error: 'No valid interest records found' });
    }

    const totalAmount = interestRecords.reduce((sum, record) => sum + parseFloat(record.interest_amount), 0);

    await db.transaction(async (connection) => {
      // Mark interest as claimed
      const placeholders = interestRecords.map(() => '?').join(',');
      await connection.execute(
        `UPDATE interest_distributions
         SET is_claimed = TRUE, claimed_at = CURRENT_TIMESTAMP
         WHERE id IN (${placeholders})`,
        interestRecords.map(r => r.id)
      );

      // Update user balance
      await connection.execute(
        `UPDATE user_balances
         SET available_balance = available_balance + ?, total_earned = total_earned + ?, updated_at = CURRENT_TIMESTAMP
         WHERE user_id = ?`,
        [totalAmount, totalAmount, userId]
      );

      // Create transaction record
      await connection.execute(
        `INSERT INTO transactions (user_id, transaction_type, amount, status)
         VALUES (?, 'interest_claim', ?, 'confirmed')`,
        [userId, totalAmount]
      );
    });

    res.json({
      message: 'Interest claimed successfully',
      amount: totalAmount,
      claimedRecords: interestRecords.length
    });

  } catch (error) {
    console.error('Interest claim error:', error);
    res.status(500).json({ error: 'Failed to claim interest' });
  }
});

// Distribute daily interest (cron job function)
async function distributeDailyInterest() {
  try {
    console.log('Starting daily interest distribution...');

    const interestRate = parseFloat(await getSystemSetting('daily_interest_rate')) || 0.01;
    const claimDeadlineHours = parseInt(await getSystemSetting('interest_claim_deadline_hours')) || 1;

    // Get all active staking records
    const activeStakes = await db.query(
      'SELECT id, user_id, amount, staking_date FROM staking_records WHERE status = "active"'
    );

    if (activeStakes.length === 0) {
      console.log('No active stakes found');
      return;
    }

    const distributionDate = new Date().toISOString().split('T')[0];
    const claimDeadline = new Date();
    claimDeadline.setHours(claimDeadline.getHours() + parseInt(claimDeadlineHours));

    await db.transaction(async (connection) => {
      for (const stake of activeStakes) {
        const interestAmount = parseFloat(stake.amount) * interestRate;

        // Check if interest already distributed for today
        const existingDistribution = await connection.execute(
          `SELECT id FROM interest_distributions
           WHERE staking_record_id = ? AND distribution_date = ?`,
          [stake.id, distributionDate]
        );

        if (existingDistribution[0].length === 0) {
          // Create interest distribution record
          await connection.execute(
            `INSERT INTO interest_distributions
             (staking_record_id, user_id, interest_amount, distribution_date, claim_deadline)
             VALUES (?, ?, ?, ?, ?)`,
            [stake.id, stake.user_id, interestAmount, distributionDate, claimDeadline]
          );

          console.log(`Distributed ${interestAmount} interest to user ${stake.user_id}`);
        }
      }
    });

    console.log('Daily interest distribution completed');

  } catch (error) {
    console.error('Daily interest distribution error:', error);
  }
}

// Send unclaimed interest to black hole (cron job function)
async function sendUnclaimedInterestToHole() {
  try {
    console.log('Processing unclaimed interest...');

    const blackHoleAddress = await getSystemSetting('black_hole_address') || '0x0000000000000000000000000000000000000000';

    // Get expired unclaimed interest
    const expiredInterest = await db.query(
      `SELECT id, user_id, interest_amount
       FROM interest_distributions
       WHERE is_claimed = FALSE AND claim_deadline < NOW() AND sent_to_hole = FALSE`
    );

    if (expiredInterest.length === 0) {
      console.log('No expired unclaimed interest found');
      return;
    }

    await db.transaction(async (connection) => {
      for (const interest of expiredInterest) {
        // Mark as sent to hole
        await connection.execute(
          'UPDATE interest_distributions SET sent_to_hole = TRUE WHERE id = ?',
          [interest.id]
        );

        console.log(`Sent ${interest.interest_amount} interest to black hole for user ${interest.user_id}`);
      }
    });

    console.log('Unclaimed interest processing completed');

  } catch (error) {
    console.error('Unclaimed interest processing error:', error);
  }
}

// Schedule daily interest distribution at 2 PM (14:00)
cron.schedule('0 14 * * *', distributeDailyInterest);

// Schedule processing of expired interest every hour
cron.schedule('0 * * * *', sendUnclaimedInterestToHole);

// Manual trigger for testing (remove in production)
router.post('/distribute-interest', authenticateToken, async (req, res) => {
  try {
    if (process.env.NODE_ENV !== 'development') {
      return res.status(403).json({ error: 'This endpoint is only available in development mode' });
    }

    await distributeDailyInterest();
    res.json({ message: 'Interest distribution triggered successfully' });

  } catch (error) {
    console.error('Manual interest distribution error:', error);
    res.status(500).json({ error: 'Failed to trigger interest distribution' });
  }
});

module.exports = {
  router,
  distributeDailyInterest,
  sendUnclaimedInterestToHole
};